﻿#define imageOrc

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using Library.Extensions;
using PLitJson;

namespace Script
{
    /// <summary>
    /// 图片查找形成excel格式并复制出来
    /// https://console.bce.baidu.com/ai/#/ai/ocr/app/list
    /// </summary>
    public class ImageFindOrc : BaseClass
    {
        public static void Main()
        {
            new ImageFindOrc();
            Console.WriteLine("已处理完毕，任意键退出！请查看生成的csv文件。");
            Console.ReadKey();
        }

#if imageOrc
        //private readonly static string APP_ID = "11074564";
        private readonly static string API_KEY = "sYyHWbN8eXXoxGfe15w5yWgy";
        private readonly static string SECRET_KEY = "1suG7480xKHWft3dmROtgbrraNMg5YU3";
        private readonly static string SELECT_EXTENSIONS = ".png|.jpg|.bmp|.tif";
        public static Baidu.Aip.Ocr.Ocr client;

        static ImageFindOrc()
        {
            foreach (var item in (GetEnvironmentVariable("TIPS") ?? "").Replace("\\n","\n").Split('\n'))
            {
                Console.WriteLine(item);
            }
            Console.WriteLine("");

            //APP_ID = GetEnvironmentVariable("APP_ID") ?? APP_ID;
            API_KEY = GetEnvironmentVariable("API_KEY") ?? API_KEY;
            SECRET_KEY = GetEnvironmentVariable("SECRET_KEY") ?? SECRET_KEY;
            SELECT_EXTENSIONS = GetEnvironmentVariable("SELECT_EXTENSIONS") ?? ".png|.jpg|.bmp|.tif";
            client = new Baidu.Aip.Ocr.Ocr(API_KEY, SECRET_KEY);
        }

        public virtual string GetResult(byte[] imageOrc)
        {
            // 调用通用文字识别, 图片参数为本地图片，可能会抛出网络等异常，请使用try/catch捕获
            var options = new Dictionary<string, object>
                {
                    {"language_type", "CHN_ENG"},
                    {"detect_direction", "true"},
                    {"detect_language", "true"},
                    {"probability", "true"}
                };

            var str = client.GeneralBasic(imageOrc, options).ToString();
            //Console.WriteLine(str);
            return str;
        }
#endif

        public ImageFindOrc()
        {
            Console.WindowWidth = (int)(Console.WindowWidth * 1.5f);
            Console.WriteLine("正在进行缓存删除操作！");
            if (Directory.Exists(".temp"))
                foreach (var item in Directory.GetFiles(".temp", "*.cache", SearchOption.AllDirectories).ForEachPaths())
                {
                    try
                    {
                        if (PMiniJSON.Json.Deserialize(File.ReadAllText(item)) is Dictionary<string, object> result)
                        {
                            int words_result_num = -1;
                            if (result.TryGetValue("words_result_num", out object value) && int.TryParse(value.ToString(), out words_result_num) && words_result_num == 0)
                            {
                                Console.WriteLine($"刪除{item}");
                                File.Delete(item);
                            }
                            else if (result.TryGetValue("error_code", out value))
                            {
                                Console.WriteLine($"刪除{item}");
                                File.Delete(item);
                            }
                        }
                    }
                    catch (Exception)
                    {
                    }
                }

            Console.WriteLine("正在进行缓存生成。。。请等待！");
            HashSet<string> hashset = new HashSet<string>();

            if (File.Exists("list.txt"))
            {
                InputPath = Directory.GetCurrentDirectory() + "/list.csv";
                hashset.UnionWith(File.ReadAllLines("list.txt"));
            }
            else
            {
                hashset.UnionWith(CheckPath(SELECT_EXTENSIONS, searchOption: SearchOption.AllDirectories));
            }

            var hashSet = new HashSet<string>(SELECT_EXTENSIONS.Split('|'), StringComparer.OrdinalIgnoreCase);
            List<string> list = hashset.Where(p => hashSet.Contains(Path.GetExtension(p))).ToList();

            foreach (var re in list.ForEachPaths(100))
            {
                FileInfo fileInfo = PathCache(re, out byte[] imageOrc);
                if (fileInfo == null) continue;
                if (fileInfo.Exists) continue;

                var str = GetResult(imageOrc).ToString();
                var result = JsonMapper.ToObject(str);
                if (result.Keys.Contains("error_code"))
                {
                    continue;
                }

                File.WriteAllText(fileInfo.FullName, str);
            }

            Console.WriteLine("正在进行结果生成。。。请等待！");

            Dictionary<string, string> dic = new Dictionary<string, string>();
            using (var streamWriter = new StreamWriter(Path.ChangeExtension(InputPath, ".csv")))
            {
                streamWriter.WriteLine("路径,是否有文字,结果路径,大小,宽度,高度");
                foreach (var re in list.ForEachPaths(3))
                {
                    FileInfo fileInfo = PathCache(re, out byte[] imageOrc);

                    Dictionary<string, object> result = new Dictionary<string, object>();

                    if (fileInfo != null && fileInfo.Exists && (PMiniJSON.Json.Deserialize(File.ReadAllText(fileInfo.FullName)) is Dictionary<string, object> dict))
                    {
                        result = dict;
                    }

                    int words_result_num = -1;
                    if (result.TryGetValue("words_result_num", out object value) && int.TryParse(value.ToString(), out words_result_num))
                    {
                    }

                    //var newPatn = re.Replace(InputPath, InputPath + "_new");
                    //new FileInfo(newPatn).Directory.Create();
                    //File.WriteAllBytes(newPatn, File.ReadAllBytes(re));

                    var image = GetExcelImage(re);
                    {
                        streamWriter.Write(re);
                        streamWriter.Write(',');
                        if (words_result_num > 0)
                        {
                            streamWriter.Write("已识别有文字");
                            streamWriter.Write(',');
                            streamWriter.Write($"file:\\\\{fileInfo.FullName}");
                        }
                        else if (words_result_num == 0)
                        {
                            streamWriter.Write("已识别无文字");
                            streamWriter.Write(',');
                            streamWriter.Write($"file:\\\\{fileInfo.FullName}");
                        }
                        else
                        {
                            streamWriter.Write("未识别");
                            streamWriter.Write(',');
                            streamWriter.Write(',');
                        }

                        streamWriter.Write(',');
                        if (new FileInfo(re).Length > 4096000) streamWriter.Write("大小大于4M了");
                        streamWriter.Write(',');
                        streamWriter.Write(image == null ? "" : image.Width.ToString());
                        streamWriter.Write(',');
                        streamWriter.Write(image == null ? "" : image.Height.ToString());
                        streamWriter.Write(',');
                        streamWriter.WriteLine();
                    }
                    image?.Dispose();
                }
            }

            //WriteAllLines(dic, InputPath);
        }

        /// <summary>
        /// 不允许非等比缩放，因为有拉伸。
        /// 图片完整URL，URL长度不超过1024字节，URL对应的图片base64编码后大小不超过4M，最短边至少15px，最长边最大4096px,支持jpg/png/bmp格式，当image字段存在时url字段失效
        /// </summary>
        /// <param name="re"></param>
        /// <param name="bytes"></param>
        /// <param name="md5"></param>
        /// <returns></returns>
        protected Image GetThumbnailImage(string re, ref byte[] bytes, ref string md5)
        {
            using (Image source = new Bitmap(re, false))
            {
                try
                {
                    int intwidth = source.Width, intHeight = source.Height;

                    if (Math.Max(source.Width, source.Height) > 4096)
                    {
                        Console.WriteLine("图片进行了缩小处理!");
                        if (source.Width > 4096)
                        {
                            intwidth = 2048;
                            intHeight = (int)(intwidth * source.Height / (float)source.Width);
                        }
                        else if (source.Height < 4096)
                        {
                            intHeight = 2048;
                            intwidth = (int)(intHeight * source.Width / (float)source.Height);
                        }
                    }
                    else if (Math.Min(source.Width, source.Height) < 32)
                    {
                        Console.WriteLine("图片进行了放大处理!");
                        if (source.Width < 32)
                        {
                            intwidth = 16;
                            intHeight = (int)(intwidth * source.Height / (float)source.Width);
                        }
                        else if (source.Height < 32)
                        {
                            intHeight = 16;
                            intwidth = (int)(intHeight * source.Width / (float)source.Height);
                        }
                    }

                    using (MemoryStream memory = new MemoryStream())
                    using (var result = new Bitmap(source, intwidth, intHeight))
                    {
                        result.Save(memory, source.RawFormat);
                        bytes = memory.ToArray();
                        md5 = GetMD5(bytes);
                        var fileInfo = new FileInfo($".temp/{md5.Substring(0, 2)}/{md5}{Path.GetExtension(re)}");
                        fileInfo.Directory.Create();
                        result.Save(fileInfo.FullName);
                        return result;
                    }
                }
                catch (Exception)
                {
                    Console.WriteLine("未识别的图片！");
                    md5 = GetMD5(bytes);
                    return source;
                }
            }
        }

        /// <summary>
        /// 成功结果缓存
        /// </summary>
        /// <param name="re"></param>
        /// <returns></returns>
        protected FileInfo PathCache(string re, out byte[] bytes)
        {
            bytes = File.ReadAllBytes(re);

            if (bytes.Length > 4096000)
            {
                return null;
            }

            string md5 = string.Empty;

            using (Image source = GetThumbnailImage(re, ref bytes, ref md5))
            {
                source.Dispose();
            }

            var fileInfo = new FileInfo($".temp/{md5.Substring(0, 2)}/{md5}.cache");
            fileInfo.Directory.Create();

            return fileInfo;
        }

#if imageOrc

        /// <summary>
        /// 用户向服务请求识别某张图中的所有文字(本地)
        /// </summary>
        public void GeneralBasicDemo()
        {
            var image = File.ReadAllBytes("图片文件路径");
            // 调用通用文字识别, 图片参数为本地图片，可能会抛出网络等异常，请使用try/catch捕获
            var result = client.GeneralBasic(image);
            Console.WriteLine(result);
            // 如果有可选参数
            var options = new Dictionary<string, object>
            {
                {"language_type", "CHN_ENG"},
                {"detect_direction", "true"},
                {"detect_language", "true"},
                {"probability", "true"}
            };
            // 带参数调用通用文字识别, 图片参数为本地图片
            result = client.GeneralBasic(image, options);
            Console.WriteLine(result);
        }

        /// <summary>
        /// 用户向服务请求识别某张图中的所有文字(网络)
        /// </summary>
        public void GeneralBasicUrlDemo()
        {
            var url = "https//www.x.com/sample.jpg";

            // 调用通用文字识别, 图片参数为远程url图片，可能会抛出网络等异常，请使用try/catch捕获
            var result = client.GeneralBasicUrl(url);
            Console.WriteLine(result);
            // 如果有可选参数
            var options = new Dictionary<string, object>
            {
                {"language_type", "CHN_ENG"},
                {"detect_direction", "true"},
                {"detect_language", "true"},
                {"probability", "true"}
            };
            // 带参数调用通用文字识别, 图片参数为远程url图片
            result = client.GeneralBasicUrl(url, options);
            Console.WriteLine(result);
        }
        #endif
    }
}